﻿using Algorithm.Check;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Algorithm.Check.ExtensionForCRC16;

namespace NewDevice.RS485
{
    /// <summary>
    /// 中盛PT100温度采集卡
    /// </summary>
    public class ZS_TemperatureCard
    {
        private SerialBase serial;
        private int slaveId;
        private string deviceName;
        private int channelCount;

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="bus"></param>
        /// <param name="slaveId">从机地址</param>
        /// <param name="channelCount">通道数量</param>
        /// <param name="name"></param>
        public ZS_TemperatureCard(SerialBase bus, int slaveId, int channelCount, string name = "温度采集卡")
        {
            serial = bus;
            this.slaveId = slaveId;
            this.channelCount = channelCount;
            this.deviceName = name;
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        /// <exception cref="NotImplementedException"></exception>
        public List<double> GetValue()
        {
            byte[] data = new byte[] {
             (byte)slaveId,
             0x04, // 功能码
             0x00, 0x00, // 寄存器地址
             (byte)((channelCount & 0xff00) >> 8), // 高字节
             (byte)(channelCount & 0xff), // 低字节
            };
            byte[] cmd = data.WithCRC16(CRC16Type.Modbus).ToArray();
            serial.deviceName = deviceName;
            var recv = serial.SendBytesAndWaitResponse(cmd, ReceivedDataCheck.FuncModbusCRC16Check);
            if (recv.Length != channelCount * 2 + 3 + 2)
            {
                throw new Exception($"{deviceName}错误的返回数据");
            }

            List<short> tmp = recv.Skip(3) // 跳过前3个字节
                 .Take(channelCount * 2)    // 每个通道2个字节
                 .Select((b, i) => new { b, i })  // 带索引的投影
                 .GroupBy(x => x.i / 2)        // 每2个字节一组
                 .Where(g => g.Count() == 2)   // 确保每组有2字节
                 .Select(g => (short)((g.First().b << 8) | g.Last().b)) // 手动位移组合
                 .ToList();

            List<double> doubles = tmp.Select(x =>
            {
                bool isNegative = (x & 0x8000) != 0; // 检查最高位是否为1
                ushort magnitude = (ushort)(x & 0x7FFF); // 取低15位数值
                return isNegative ? magnitude * -0.1 : magnitude * 0.1;
            }).ToList();
            return doubles;
        }
    }
}